package com.gitee.magic.core.utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.gitee.magic.core.exception.ApplicationException;

/**
 * @author start
 */
public class ReflectUtils {

	/**
	 * 根据属性，拿到set方法，并把值set到对象中
	 * @param obj
	 * @param clazz
	 * @param filedName
	 * @param typeClass
	 * @param value
	 */
	public static void setValue(Object obj, Class<?> clazz, String filedName, Class<?> typeClass, Object value) {
		String firstChar = filedName.substring(0, 1).toUpperCase();
		String methodName = "set" + firstChar + filedName.substring(1);
		try {
			Method method = clazz.getDeclaredMethod(methodName, new Class[] { typeClass });
			method.invoke(obj, value);
		} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			throw new ApplicationException(e);
		}
	}

	public static void invoke(Object instance, String methodName) {
		try {
			Method method = instance.getClass().getMethod(methodName);
			method.invoke(instance);
		} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			throw new ApplicationException(e);
		}
	}

	/**
	 * 判断类是否实现了某接口
	 * @param c
	 * @param szInterface
	 * @return
	 */
	public static boolean isInterface(Class<?> c, Class<?> szInterface) {
		Class<?>[] face = c.getInterfaces();
		for (int i = 0, j = face.length; i < j; i++) {
			if (face[i].equals(szInterface)) {
				return true;
			} else {
				Class<?>[] face1 = face[i].getInterfaces();
				for (int x = 0; x < face1.length; x++) {
					if (face1[x].equals(szInterface)) {
						return true;
					} else if (isInterface(face1[x], szInterface)) {
						return true;
					}
				}
			}
		}
		if (null != c.getSuperclass()) {
			return isInterface(c.getSuperclass(), szInterface);
		}
		return false;
	}

	public static boolean isSuperClass(Class<?> c, Class<?> cls) {
		return cls.isAssignableFrom(c);
	}

	public static <T>T newInstance(Class<T> prototype) {
		try {
			return prototype.getDeclaredConstructor().newInstance();
		} catch (InstantiationException | IllegalAccessException | 
				IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
			throw new ApplicationException(e);
		}
	}
	
}
